#ifndef AFCORE_COMMON_UTILITY_RAND_
#define AFCORE_COMMON_UTILITY_RAND_

#include <memory>
#include <thread>

#include "define.h"
#include "duration.h"
#include "nocopyable.h"

namespace afcore {

/// @brief  随机相关
class AFCORE_COMMON_API CRandom
  : public CNocopyable {
public:
  /// @brief  单例
  /// @return 随机相关
  static CRandom& Instance();

  /// @brief  uint32_t随机
  /// @return [0, UINT32_MAX)
  uint32_t Rand32();

  /// @brief  int32_t随机
  /// @param  min     随机范围的最小值 默认 0
  /// @param  max     随机范围的最大值 默认值 INT32 - 1
  /// @return [min, max] (max - min < INT32_MAX)
  /// @note   max >= min 需要调用者保证
  int32_t RandI32(int32_t min = 0,
                  int32_t max = std::numeric_limits<int32_t>::max() - 1);

  /// @brief  uint32_t随机
  /// @param  min     随机范围的最小值 默认 0
  /// @param  max     随机范围的最大值 默认 UINT32 - 1
  /// @return [min, max] (max - min < UINT32_MAX)
  /// @note   max >= min 需要调用者保证
  uint32_t RandU32(uint32_t min = 0,
                   uint32_t max = std::numeric_limits<uint32_t>::max() - 1);

  /// @brief  float随机
  /// @param  min     随机范围的最小值 默认 std::numeric_limits<float>::min()
  /// @param  max     随机范围的最大值 默认 std::numeric_limits<float>::max()
  /// @return [min, max)
  /// @note   max >= min 需要调用者保证
  float RandFloat(float min = std::numeric_limits<float>::min(),
                  float max = std::numeric_limits<float>::max());

  /// @brief  double随机
  /// @return [0.0, 1.0)
  double RandDouble();

  /// @brief  毫秒随机 uint32_t<br>
  ///         相当于 RandU32(min * IN_MILLISECONDS, max * IN_MILLISECONDS)
  /// @param  min     毫秒最小值 默认 0
  /// @param  max     毫秒最大值 默认 std::numeric_limits<uint32_t>::max() / RMilliseconds::period::den
  /// @return [min, max]
  /// @note   max >= min 需要调用者保证<br>
  ///         (std::numeric_limits<uint32_t>::max() / RMilliseconds::period::den) >= max
  uint32_t RandMS(uint32_t min = 0,
                  uint32_t max = std::numeric_limits<uint32_t>::max() / RMilliseconds::period::den);

  /// @brief  毫秒精度时间，误差位uint32_t时有效
  /// @param  min     时间最小值
  /// @param  max     时间最大值
  /// @return [min, max) (max - min <= UINT32_MAX)
  /// @note   调用者需要保证<br>
  ///         max.count() - min.count() 在 [0 , 0xFFFFFFFF)范围内
  RMilliseconds RandTime(const RMilliseconds &min, const RMilliseconds &max);

  /// @brief  机会随机
  /// @return [0.0, 100.0)
  double RandChance();

  /// @brief  随机带权重的随机数
  /// @return [0, count)
  uint32_t RandU32Weighted(size_t count, double const *weights);

  /// @brief  根据给的机会roll，返回roll中的结果
  /// @return 大于机会true 否则flase
  inline bool RollChanceFloat(float chance) { return chance > RandChance(); }

  /// @brief  根据给的机会roll，返回roll中的结果
  /// @return 大于机会true 否则flase
  inline bool RollChanceI32(int32_t chance) { return chance > RandI32(0, 99); }

  /// @brief  获取随机种子
  /// @return 随机种子
  static int seed() { return seed_; }

  /// @brief  获取下一个可用的随机种子
  /// @return 可用的随机种子
  static int GetNextSeed() { return ++seed_; }

private:
  static int seed_; ///< 随机种子 每个线程的随机种子都是不同的
};

/// @brief  随机生成器
class AFCORE_COMMON_API CSMFTEngine
  : public CNocopyable {
public:
  /// @brief  结果类型
  using result_type = uint32_t;

  /// @brief  单例
  /// @return 随机生成器
  static CSMFTEngine& Instance();

  /// @brief  接口 最小值
  /// @return uint32_t 类型最小值
  static constexpr result_type min() {
    return std::numeric_limits<result_type>::min();
  }

  /// @brief  接口 最大值
  /// @return uint32_t 类型最大值
  static constexpr result_type max() {
    return std::numeric_limits<result_type>::max();
  }

  /// @brief  ()操作符重载
  /// @return uint32_t 类型的随机数
  result_type operator()() const { return CRandom::Instance().Rand32(); }
};

} // !namespace afcore

#endif // !AFCORE_COMMON_UTILITY_RAND_